package com.gitee.huanminabc.jlambda_sql.jdbc;

import com.gitee.huanminabc.jcommon.str.StringIdentifyUtil;

/**
 * sql工具类
 */
public class SqlUtil {

    //防止sql注入 ,一般只有查询的时候才使用, 参考的事mysql的jdbc驱动
    public static String escapeSql(String parameter) {
        //去掉%和_ ,防止like注入 , 不能通过参数传递必须在sql中写死
        if (parameter.contains("%") || parameter.contains("_")) {
            parameter = parameter.replace("%", "").replace("_", "");
        }

        if (isEscapeNeededForString(parameter, parameter.length())) {
            parameter = escapeString(parameter);
        }
        //判断如果不是数值类型,那么需要加上单引号
        if (!StringIdentifyUtil.isNumeric(parameter)) {
            parameter = "'" + parameter + "'";
        }
        return parameter;
    }

    private static String escapeString(String x) {
        StringBuilder buf = new StringBuilder((int) (x.length() * 1.1));
        for (int i = 0; i < x.length(); ++i) {
            char c = x.charAt(i);
            switch (c) {
                case 0: //0表示空字符
                    buf.append('\\');
                    buf.append('0');
                    break;
                case '\n':
                    buf.append('\\');
                    buf.append('n');
                    break;
                case '\r':
                    buf.append('\\');
                    buf.append('r');
                    break;
                case '\\':
                    buf.append('\\');
                    buf.append('\\');
                    break;
                case '\'':  //字符串中出现单引号,那么需要转义不然可以注入
                    buf.append('\\');
                    buf.append('\'');
                    break;
                case '"': // 一般数据库中不会出现这个字符,但是为了安全还是转义
                    buf.append('\\');
                    buf.append('"');
                    break;
                case '\032': //  这是一个特殊字符，会在Win32上出现问题
                    buf.append('\\');
                    buf.append('Z');
                    break;
                default:
                    buf.append(c);
            }
        }
        return buf.toString();
    }

    //判断是否需要转义
    private static boolean isEscapeNeededForString(String x, int stringLength) {
        boolean needsHexEscape = false;

        for (int i = 0; i < stringLength; ++i) {
            char c = x.charAt(i);

            switch (c) {
                case 0:
                case '\n':
                case '\r':
                case '\\':
                case '\'':
                case '"': /* Better safe than sorry */
                case '\032': /* This gives problems on Win32 */
                    needsHexEscape = true;
                    break;
            }

            if (needsHexEscape) {
                break; // no need to scan more
            }
        }
        return needsHexEscape;
    }


}
